#ifndef RSIM_CDATA_H
#define RSIM_CDATA_H

/* -------------------------------------------------------------------------- *
 * File: CData.h                                                              *
 * Authors: Kishor Bhalerao                                                   *
 * Email : kishor8dm@gmail.com                                                *
 * Contributors:                                                              *
 * Email:                                                                     *
 * copyright (c) 2010 Authors.                                                *
 *                                                                            *
 * This program is free software: you can redistribute it and/or modify it    *
 * under the terms of the GNU General Public License as published by the Free *
 * Software Foundation, either version 3 of the License, or any later version.*
 *                                                                            *
 * This program is distributed in the hope that it will be useful, but        *
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License   *
 * for more details. (http://www.gnu.org/licenses/)                           *
 * -------------------------------------------------------------------------- */
#include <iostream>

namespace RSIM{
        
/**
This is the base container classes for Matrix and Vector. The data is stored in 
a contiguous block of length equal to the number of elements in the matrix/vector.
The indexing is 0 based. 
*/


template <class T,int N>
class cData{
        public:
                /** This stores the actual data */
                T *data_;                                
                
                /** This is the number of elements. Here to allow resizing the 
                vectors/matrices on the fly */
                int nele_;
                
                /** Allocate memory if required */
                cData():data_(NULL),nele_(N){
                        if(nele_)
                                data_ = new T[nele_];
                }
                
                /** Set each element to val */
                cData(const T& val):data_(NULL),nele_(N){
                        if(nele_){
                                data_ = new T[nele_];
                                for(int i=0;i<nele_;data_[i++]=val);
                        }
                }
                
                /** Deep copy */
                template <class P,int K>
                cData(const cData<P,K>& Ar):data_(NULL),nele_(N){                        
                        if(nele_){
                                data_ = new T[nele_];
                                const T *ptr = Ar.Ptr();
                                for(int i=0;i<nele_;++i)
                                        data_[i] = ptr[i];
                        }
                }                                
                
                /** Deep copy */
                void operator=(const cData& Ar){
                        clear();
                        nele_ = Ar.getLength();
                        if(nele_){
                                data_ = new T[nele_];
                                const T *ptr = Ar.Ptr();
                                for(int i=0;i<nele_;++i)
                                        data_[i] = ptr[i];
                        }
                }                                                                                                
                
                /** Clear memory */
                ~cData(){
                        delete [] data_;
                }
                
        public:
                
                /** Clear memory. Results in NULL pointer */
                void clear(){
                        delete [] data_; 
                        data_ = NULL; 
                        nele_ = 0;
                }
                                
                /** @param len Clear memory if already allocated. Allocate contiguous block of memory */
                void resize(const int& len){
                        delete []data_;
                        nele_ = len;
                        if(nele_)
                                data_ = new T[len];
                }
                
                void resize(const int& row,const int& col){
                        delete []data_;
                        data_ = NULL;
                        nele_ = row*col;
                        if(nele_)
                                data_ = new T[nele_];
                }
                
                /** Caution: No check on validity of input */
                const T& getElement(const int& i)const{return data_[i];}
                
                /** Caution: No check on validity of input */
                T& wgetElement(const int& i){return data_[i];}
                
                /** Set all elements to zero */
                void Zeros(){
                        if(nele_)
                                for(int i=0;i<nele_;data_[i++]=0);
                }
                
                /** Return the sum of all elements */
                T sum()const{
                        T op(0);
                        for(int i=0;i<nele_; op += data_[i++]);
                        return op;
                }
                
                /** get length of the contiguous block */
                int getLength() const{
                        return nele_;
                }
                
                /** @return Returns a const pointer to the data of the function */
                const T* Ptr() const{return data_;}
                
                /** @return Writable (w) pointer to the data. */
                T* wPtr(){return data_;}
                
                /**
                @param ptr Array from which data is to be copied.
                @param index Vector[index] = ptr[0], Vector[index+1] = ptr[1] and so on.
                @param num Number of values to be copied
                Caution: No error check on the input
                */
                void copy(const T *ptr, const int& index, const int& num){
                        for(int i=0;i<num;++i)
                                data_[index+i] = ptr[i];
                }
        
}; // class cData
} // namespace RSIM

#endif